<template>
  <el-dialog v-model="state.importVisible" draggable title="导入数据" width="980px" center destroy-on-close>
    <section class="dialog-body">
      <section class="import-wrap">
        <input ref="excelUploadInput" style="display: none" type="file" accept=".xlsx, .xls" @change="handleClick" />
        <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
          拖拽 Excel 导入模板文件 到这里 或者
          <el-button :loading="state.loading" style="margin-left: 16px" size="mini" type="primary" @click="handleUpload">
            选择文件 </el-button>
        </div>
      </section>
      <div class="mt10">没有Excel模板？<el-button size="mini" text @click="createTemplate"> 点我创建模板 </el-button></div>
    </section>
    <template #footer>
			<span class="dialog-footer">
				<el-button>取消</el-button>
				<el-button type="primary" :disabled="state.importDataPool && state.importDataPool.length === 0"> 确认导入
				</el-button>
			</span>
    </template>
  </el-dialog>
</template>
<script setup lang="ts" name="importTable">
import { ElMessage } from 'element-plus';
import { reactive, nextTick, ref } from 'vue';
// import table2excel from './index.js';
import table2excel from 'js-table2excel';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import tools from '../../utils/toolsTable';
import * as XLSX from 'xlsx';
const excelUploadInput = ref();
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const emits = defineEmits(['import']);
const state = reactive<any>({
  importVisible: false,
  importConfig: [], //导入的所需关键字
  importHeader: '',
  importDataPool: [], //生成的导入数据
  loading: false,
  excelData: {
    header: null,
    results: null,
  },
});
function createTemplate() {
  if (!state.importConfig) {
    ElMessage.error('列表未设置导入关键字');
    return
  }
  let headers = state.importHeader.filter((head: any) => state.importConfig.includes(head.key));
  let params = <any>{};
  headers.map((key: any, index: number) => {
    params[state.importConfig[index]] = '';
  });
  console.log(params, '格式化回调');
  nextTick(() => {
    table2excel(headers, [params], `导入模板 ${new Date().toLocaleString()}`);
  });
}
function beforeUpload(file: any) {
  const isLt1M = file.size / 1024 / 1024 < 1;
  if (isLt1M) {
    return true;
  }
  ElMessage.warning('Please do not upload files larger than 1m in size.');
  return false;
}
function generateData(event: any) {
  let { header, results } = event;
  console.log(state.importHeader, 'state.importHeader');
  console.log(state.importConfig, 'state.importConfig');
  state.excelData.header = state.importHeader.map((item: any) => {
    if (header.includes(item.title)) {
      return item.key;
    }
  });
  state.excelData.results = results.map((item: any, index: number) => {
    let obj = <any>{};
    state.importHeader.map((child: any) => {
      obj[child.key] = item[child.title];
    });
    return obj;
  });
  state.importVisible = false;
  emits('import', state.excelData);
  // state.onSuccess && state.onSuccess(state.excelData);
}
function handleDrop(e: any) {
  e.stopPropagation();
  e.preventDefault();
  if (state.loading) return;
  const files = e.dataTransfer.files;
  if (files.length !== 1) {
    ElMessage.error('Only support uploading one file!');
    return;
  }
  const rawFile = files[0]; // only use files[0]

  if (!isExcel(rawFile)) {
    ElMessage.error('Only supports upload .xlsx, .xls, .csv suffix files');
    return false;
  }
  upload(rawFile);
  e.stopPropagation();
  e.preventDefault();
}
function handleDragover(e: any) {
  e.stopPropagation();
  e.preventDefault();
  e.dataTransfer.dropEffect = 'copy';
}
function handleUpload() {
  excelUploadInput.value.click();
}
function handleClick(e: any) {
  const files = e.target.files;
  const rawFile = files[0]; // only use files[0]
  if (!rawFile) return;
  upload(rawFile);
}
function upload(rawFile: any) {
  excelUploadInput.value.value = null; // fix can't select the same excel

  if (!beforeUpload) {
    readerData(rawFile);
    return;
  }
  const before = beforeUpload(rawFile);
  if (before) {
    readerData(rawFile);
  }
}
function readerData(rawFile: any) {
  state.loading = true;
  return new Promise((resolve: any, reject: any) => {
    const reader = new FileReader();
    reader.onload = (e: any) => {
      const data = e.target.result;
      const workbook = XLSX.read(data, { type: 'array' });
      const firstSheetName = workbook.SheetNames[0];
      const worksheet = workbook.Sheets[firstSheetName];
      const header = getHeaderRow(worksheet);
      const results = XLSX.utils.sheet_to_json(worksheet);
      generateData({ header, results });
      state.loading = false;
      resolve();
    };
    reader.readAsArrayBuffer(rawFile);
  });
}
function getHeaderRow(sheet: any) {
  const headers = [];
  const range = XLSX.utils.decode_range(sheet['!ref']);
  let C;
  const R = range.s.r;
  /* start in the first row */
  for (C = range.s.c; C <= range.e.c; ++C) {
    /* walk every column in the range */
    const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
    /* find the cell in the first row */
    let hdr = 'UNKNOWN ' + C; // <-- replace with your desired default
    if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
    headers.push(hdr);
  }
  return headers;
}
function isExcel(file: any) {
  return /\.(xlsx|xls|csv)$/.test(file.name);
}
function initComponent(header: any, config: string[]) {
  state.importVisible = true;
  state.importHeader = header;
  state.importConfig = config;
}
function formatImport(targetObject: any, propsArray: any) {
  if (typeof targetObject !== 'object' || !Array.isArray(propsArray)) {
    throw new Error('参数格式不正确');
  }
  const result = <any>{};
  Object.keys(targetObject)
      .filter((key) => propsArray.includes(key))
      .forEach((key) => {
        result[key] = targetObject[key];
      });
  return result;
}

function formatData(data: any, header: any) {
  return new Promise((resolve, reject) => {
    let exportData = tools.deepCopy(data);
    let fomatTask = header.filter((item: any) => item.type === 'format' || item.type === 'tag' || item.type === 'switch');
    data.map((item: any, index: number) => {
      fomatTask.map((keys: any) => {
        if (keys.type === 'format' || keys.type === 'tag') {
          exportData[index][keys.key] = keys.options.filter((values: any) => values.value === item[keys.key])[0].label;
        } else if (keys.type === 'switch') {
          exportData[index][keys.key] = exportData[index][keys.key] === keys.active ? keys.activeText || '启用' : keys.inactiveText || '禁用';
        }
      });
    });
    resolve(exportData);
  });
}
//导出表格 自动识别
//导出表格 自动识别
async function ExportTable(dataPool: any, header: any, name: any) {
  console.log(dataPool, header);
  if (dataPool && dataPool.length > 0) {
    let headerData = header.filter(
        (keys: any) => keys.type === 'text' || keys.type === 'image' || keys.type === 'format' || keys.type === 'tag' || keys.type === 'switch'
    );
    let formatResult: any = await formatData(dataPool, headerData);
    let tableKey = headerData.map((res: any) => res.key);
    let importData = <any>[];
    formatResult.map((item: any) => {
      importData.push(formatImport(item, tableKey));
    });
    console.log(headerData, 'headerData');
    console.log(importData, 'importData');
    /*
         如果此处报错 TypeError: typeMap[(col.type || "text")] is not a function
         请前往 /node_modules/js-table2excel/index.js 下 第126行代码 新增typeMap类型
         image: getImageHtml,
     text: getTextHtml,
     format: getTextHtml,
     tag: getTextHtml,
     switch: getTextHtml,
         修改node_modules 需要重新运行项目
         前提请确保已经引入 js-table2excel  否则请先引入npm包
        */
    nextTick(() => {
      table2excel(headerData, importData, `${themeConfig.value.globalTitle}【${name}】${new Date().toLocaleString()}`);
    });
  } else {
    ElMessage.error('暂无可导出数据');
    return;
  }
}
defineExpose({
  initComponent,
  ExportTable,
});
</script>
<style lang="scss" scoped>
.dialog-body {
  display: flex;
  flex-direction: column;
  align-items: center;

  .import-wrap {
    width: 375px;
    height: 135px;
    border-color: var(--el-color-primary);
    border: 1px dashed var(--el-border-color);

    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
}
</style>
